/**
 * 
 */
package org.rollinitiative.d20.entity;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rollinitiative.d20.AdjustableValue;
import org.rollinitiative.d20.Adjustment;
import org.rollinitiative.d20.AdjustmentListener;
import org.rollinitiative.d20.Adjustment.AdjustmentSource;

/**
 * The AbilityValue extends the basic AdjustableValue in order to provide event-driven notification
 * to subscribers of changes in the Ability modifier due to current Ability value.
 * 
 * @author bebopjmm
 * 
 */
public class AbilityValue extends AdjustableValue
{
    static final Log LOG_ = LogFactory.getLog(AbilityValue.class);

    public static final int DEFAULT_VALUE = 10;

    /**
     * Ability Modifer adjustment
     */
    Adjustment abilityMod_;

    /**
     * Ability that this AbilityValue is associated with.
     */
    Ability ability_;


    /**
     * Initializes an AbilityValue to have the specified baseValue and no subscribers.
     * 
     * @param baseValue base value for the AdjustableValue
     * @param ability Ability that this AbilityValue represents
     */
    public AbilityValue(int baseValue, Ability ability)
    {
        super(baseValue);
        this.ability_ = ability;
        abilityMod_ = new Adjustment(AdjustmentSource.INHERENT, Ability
                .getModifier(this.getCurrent()), ability.name());
    }


    /**
     * @return the Ability enum that this AbilityValue is associated with.
     */
    public Ability getAbility()
    {
        return ability_;
    }


    /**
     * @return The ability modifier adjustment for this ability value.
     */
    public Adjustment getModifier()
    {
        return abilityMod_;
    }


    /**
     * Triggers update the ability modifier Adjustment and subscriber notification following
     * baseValue change.
     * 
     * @param baseValue the baseValue to set
     * @since incr-0.1
     */
    @Override
    public synchronized void setBase(int baseValue)
    {
        super.setBase(baseValue);
        updateAdjustment();
    }


    /**
     * This method returns the ability modifier value for the current ability value.
     * 
     * @return current ability modifer value.
     */
    public int getAbilityModifier()
    {
        return abilityMod_.getValue();
    }


    @Override
    public synchronized void addAdjustment(Adjustment adjustment)
    {
        LOG_.debug("Adding new Adjustment: " + adjustment.getDescription());
        super.addAdjustment(adjustment);
        updateAdjustment();
    }


    @Override
    public synchronized void removeAdjustment(Adjustment adjustment)
    {
        LOG_.debug("Removing Adjustment: " + adjustment.getDescription());
        super.removeAdjustment(adjustment);
        updateAdjustment();

    }


    /*
     * (non-Javadoc)
     * 
     * @see
     * org.rollinitiative.d20.AdjustmentListener#valueChanged(org.rollinitiative.d20.Adjustment)
     */
    @Override
    public void valueChanged(Adjustment adjustment)
    {
        super.valueChanged(adjustment);
        updateAdjustment();
    }


    /**
     * Updates the ability modifier value and notifies all subscribers.
     */
    void updateAdjustment()
    {
        abilityMod_.setValue(Ability.getModifier(this.getCurrent()));
        LOG_.debug("New abilityMod = " + abilityMod_.getValue());
    }

}
